package com.tcoiss.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcoiss.app.domain.AdminDivision;
import com.tcoiss.app.domain.AscoOrderForm;
import com.tcoiss.app.domain.KdQdfile;
import com.tcoiss.app.service.IAdminDivisionService;
import com.tcoiss.app.service.IAscoOrderFormService;
import com.tcoiss.app.service.IKdQdfileService;
import com.tcoiss.app.service.ITrackServiceService;
import com.tcoiss.common.core.enums.ErroEnums;
import com.tcoiss.common.core.exception.CustomException;
import com.tcoiss.common.core.text.UUID;
import com.tcoiss.app.mapper.AscoOrderFormMapper;
import com.tcoiss.common.component.api.model.AddressVo;
import com.tcoiss.common.component.service.ApiHelperService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 财神订单Service业务层处理
 *
 * @author zw
 * @date 2021-08-30
 */
@Service
@Log4j2
public class AscoOrderFormServiceImpl extends ServiceImpl<AscoOrderFormMapper, AscoOrderForm> implements IAscoOrderFormService {

    @Autowired
    private ITrackServiceService iTrackServiceService;

    @Autowired
    private ApiHelperService apiHelperService;

    @Autowired
    IKdQdfileService iKdQdfileService;

    @Autowired
    IAdminDivisionService iAdminDivisionService;

    @Autowired
    private AscoOrderFormMapper ascoOrderMapper;

    private String gaode_key;

    @Override
    public List<AscoOrderForm> queryList(AscoOrderForm ascoOrderForm) {
        LambdaQueryWrapper<AscoOrderForm> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(ascoOrderForm.getNameAttn())){
            lqw.eq(AscoOrderForm::getNameAttn ,ascoOrderForm.getNameAttn());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getPhoneAttn())){
            lqw.eq(AscoOrderForm::getPhoneAttn ,ascoOrderForm.getPhoneAttn());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getProvinceAttn())){
            String province=ascoOrderForm.getProvinceAttn().toUpperCase();
            if("NULL".equals(province)||"空".equals(province)){
//                lqw.eq(AscoOrderForm::getProvinceAttn ,"");
                lqw.isNull(AscoOrderForm::getProvinceAttn);
            }if("不是江西省".equals(province)){
                lqw.isNotNull(AscoOrderForm::getProvinceAttn);
            }else{
                lqw.eq(AscoOrderForm::getProvinceAttn ,ascoOrderForm.getProvinceAttn());
            }

        }
        if (StringUtils.isNotBlank(ascoOrderForm.getCityAttn())){
            lqw.eq(AscoOrderForm::getCityAttn ,ascoOrderForm.getCityAttn());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getDistrictAttn())){
            lqw.eq(AscoOrderForm::getDistrictAttn ,ascoOrderForm.getDistrictAttn());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getAdministrativeAttn())){
            lqw.eq(AscoOrderForm::getAdministrativeAttn ,ascoOrderForm.getAdministrativeAttn());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getAddressAttn())){
            lqw.like(AscoOrderForm::getAddressAttn ,ascoOrderForm.getAddressAttn());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getItemName())){
            lqw.like(AscoOrderForm::getItemName ,ascoOrderForm.getItemName());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getGoodsNo())){
            lqw.eq(AscoOrderForm::getGoodsNo ,ascoOrderForm.getGoodsNo());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getSaleAttr())){
            lqw.eq(AscoOrderForm::getSaleAttr ,ascoOrderForm.getSaleAttr());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getNameSender())){
            lqw.eq(AscoOrderForm::getNameSender ,ascoOrderForm.getNameSender());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getPhoneSender())){
            lqw.eq(AscoOrderForm::getPhoneSender ,ascoOrderForm.getPhoneSender());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getProvinceSender())){
            lqw.eq(AscoOrderForm::getProvinceSender ,ascoOrderForm.getProvinceSender());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getCitySender())){
            lqw.eq(AscoOrderForm::getCitySender ,ascoOrderForm.getCitySender());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getDistrictSender())){
            lqw.eq(AscoOrderForm::getDistrictSender ,ascoOrderForm.getDistrictSender());
        }
        if (StringUtils.isNotBlank(ascoOrderForm.getAddressSender())){
            lqw.eq(AscoOrderForm::getAddressSender ,ascoOrderForm.getAddressSender());
        }
        return this.list(lqw);
    }

    /**
     *
     * @param columns 用户数据列表
     * @param updateSupport 是否更新支持，如果已存在，则进行更新数据
     * @return 结果
     */
    @Override
    public String importTable(List<AscoOrderForm> columns, boolean updateSupport) {
        // 判断传入参数是否为空
        if (com.tcoiss.common.core.utils.StringUtils.isNull(columns) || columns.size() == 0) {
            throw new CustomException(ErroEnums.DATAERRO.getCode(),new Object[]{},"导入数据不能为空！");
        }
        gaode_key=iTrackServiceService.getDefaultKey().getGaodeKey();
        for(int i=0;i<columns.size();i++){
            AscoOrderForm ascoOrder=columns.get(i);
            String rgion=ascoOrder.getRegion();
            String excAddress=ascoOrder.getAddress();
            String addressAttn=rgion+excAddress;
            addressAttn=addressAttn.replaceAll(" ","");
            //如果上传的数据这些字段全为空,去掉当前行
            if((ascoOrder.getReceiveAmtBillNo()==null||"".equals(ascoOrder.getReceiveAmtBillNo().replaceAll(" ","")))
                    &&(rgion==null||"".equals(rgion.replaceAll(" ","")))
                    &&(excAddress==null||"".equals(excAddress.replaceAll(" ","")))
                    &&(ascoOrder.getAddressAttn()==null||"".equals(ascoOrder.getAddressAttn().replaceAll(" ","")))
                    &&(ascoOrder.getItemName()==null)||"".equals(ascoOrder.getItemName().replaceAll(" ",""))
            ){
                columns.remove(i);
                continue;
            }
        }
        StringBuilder successMsg = new StringBuilder();
        //批次号，用于第二遍筛选取数据
        String batchIndex=UUID.randomUUID().toString();
        int returnNum=isOrStartMultithreading(columns,batchIndex);//超过2000条启动多线程
//        if (this.saveBatch(columns)) {
//            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + columns.size() + " 条，数据如下：");
//        } else {
//            throw new DataException("500", null, "保存表的列数据异常");
//        }
        if(returnNum!=0){
            successMsg.insert(0, "恭喜您，数据导入成功！共 " + returnNum + " 条，数据如下：");
        }else{
            int num=this.count();
            if(num==0){
                successMsg.insert(0, "操作失败，请联系管理员!");
            }else{
                successMsg.insert(0, "恭喜您，数据导入成功！共 " + num + " 条，数据如下：");
            }
         }
        //第二遍筛选
        AscoOrderForm secondAscoOrder=new AscoOrderForm();
//        secondAscoOrder.setProvinceAttn("江西省");
        secondAscoOrder.setBatchIndex(batchIndex);
        secondAscoOrder.setItemName("四平电商");//门店名称为"四平电商" 是电商配送的不做二次筛选
        List<AscoOrderForm>  secondList=this.queryListByAscoOrderForm(secondAscoOrder);
        secondSearchUpdateData(secondList);
//        this.saveOrUpdateBatch(secondList);

        //批量修改状态
        ascoOrderMapper.updateSuccessStatusByBatchId(batchIndex);
        return successMsg.toString();
    }

    //处理特殊地址并且直接返回值不调接口
    private boolean processOtherAdressSetValue( AscoOrderForm ascoOrder){
       boolean returnFlag=false;
        if(ascoOrder.getAddressAttn().contains("九龙湖管理处")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("南昌市");
            ascoOrder.setDistrictAttn("红谷滩区");
            ascoOrder.setAdministrativeAttn("江西省/南昌市/红谷滩区/九龙湖管理处");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("青云谱郊区")&&ascoOrder.getAddressAttn().contains("幽兰镇")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("南昌市");
            ascoOrder.setDistrictAttn("南昌县");
            ascoOrder.setAdministrativeAttn("江西省/南昌市/南昌县/幽兰镇");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("寻乌九洲国际")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("赣州市");
            ascoOrder.setDistrictAttn("寻乌县");
            ascoOrder.setAdministrativeAttn("江西省/赣州市/寻乌县/文峰乡");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("新城城泰江来")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("南昌市");
            ascoOrder.setDistrictAttn("西湖区");
            ascoOrder.setAdministrativeAttn("江西省/南昌市/西湖区/桃花镇");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("赣州南康南康市工业三路路口105国道旁边")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("赣州市");
            ascoOrder.setDistrictAttn("南康区");
            ascoOrder.setAdministrativeAttn("江西省/赣州市/南康区/南康市工业园");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("庐山区十里街道办事处")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("九江市");
            ascoOrder.setDistrictAttn("濂溪区");
            ascoOrder.setAdministrativeAttn("江西省/九江市/濂溪区/十里街道");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("南昌县")&&ascoOrder.getAddressAttn().contains("金沙大道")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("南昌市");
            ascoOrder.setDistrictAttn("南昌县");
            ascoOrder.setAdministrativeAttn("江西省/南昌市/南昌县/小蓝经济开发区");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("德兴县")&&ascoOrder.getAddressAttn().contains("银河街道")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("上饶市");
            ascoOrder.setDistrictAttn("德兴市");
            ascoOrder.setAdministrativeAttn("江西省/上饶市/德兴市/银城街道");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("庐山区莲花镇")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("九江市");
            ascoOrder.setDistrictAttn("濂溪区");
            ascoOrder.setAdministrativeAttn("江西省/九江市/濂溪区/莲花镇");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("樟树市")&&ascoOrder.getAddressAttn().contains("淦阳街道")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("宜春市");
            ascoOrder.setDistrictAttn("樟树市");
            ascoOrder.setAdministrativeAttn("江西省/宜春市/樟树市/淦阳街道");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("赣州崇义龙勾")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("赣州市");
            ascoOrder.setDistrictAttn("崇义县");
            ascoOrder.setAdministrativeAttn("江西省/赣州市/崇义县/龙勾乡");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("上高县敖阳街道")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("宜春市");
            ascoOrder.setDistrictAttn("上高县");
            ascoOrder.setAdministrativeAttn("江西省/宜春市/上高县/敖阳街道");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("九江修水修水县水木清华")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("九江市");
            ascoOrder.setDistrictAttn("修水县");
            ascoOrder.setAdministrativeAttn("江西省/九江市/修水县/义宁镇");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("南昌县")&&ascoOrder.getAddressAttn().contains("新力银湖湾")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("南昌市");
            ascoOrder.setDistrictAttn("南昌县");
            ascoOrder.setAdministrativeAttn("江西省/南昌市/南昌县/小蓝经济开发区");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("东乡县毛连山")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("抚州市");
            ascoOrder.setDistrictAttn("东乡区");
            ascoOrder.setAdministrativeAttn("江西省/抚州市/东乡区/金峰街道");
            returnFlag=true;
        }
        if(ascoOrder.getAddressAttn().contains("南康市")&&ascoOrder.getAddressAttn().contains("东山街道办事处")){
            ascoOrder.setProvinceAttn("江西省");
            ascoOrder.setCityAttn("赣州市");
            ascoOrder.setDistrictAttn("南康区");
            ascoOrder.setAdministrativeAttn("江西省/赣州市/南康区/东山街道");
            returnFlag=true;
        }
        return returnFlag;
    }


    //处理特殊地址
    private String processOtherAdress(String address){
        if(address.contains("南康市")){
//            if(addressAttn.indexOf("南康市")>0){//因为南康市在字符串最前面，就返回0，判断不出来
            address=address.replace("南康市","赣州市南康市");
        }
//        if(address.contains("庐山区")){//address.contains("庐山市")
//            address=address.replace("庐山区","九江市庐山区");
//        }
        if(address.contains("乐平县")){
            address=address.replace("乐平县","景德镇市乐平县");
        }
//        if(address.contains("德兴县")){
//            address=address.replace("德兴县","上饶市德兴县");
//        }
        if(address.contains("新干县")){
            address=address.replace("新干县","吉安市新干县");
        }
        if(address.contains("电商配送")){
            address=address.replace("电商配送","");
        }
//        if(address.contains("（次配）")){
//            address=address.replace("（次配）","");
//        }
        return address;
    }


    private void secondSearchUpdateData(List<AscoOrderForm> columns){
        if(columns!=null){
            if(columns.size()<=150){
                for(int i=0;i<columns.size();i++){
                    AscoOrderForm ascoOrder=columns.get(i);
                    //if(ascoOrder.getAddressAttn().contains("配送")){
                    //查询地址默认自带江西省
                    String addressAttn="江西省"+ascoOrder.getAddressAttn();
                    //一条一条查
                    secondCallInterfaceEncapsulateData(ascoOrder,addressAttn,i);
                }
            }else{
                ExecutorService exe = Executors.newFixedThreadPool(50);
                //List<List<AscoOrderForm>> columnsList=averageAssign(columns,2000);
                List<List<AscoOrderForm>> columnsList=fixedGrouping(columns,150);
//            final boolean[] flagArr = new boolean[columnsList.size()];
//            int overSize=0;//记录最后一个集合的数量
                for(int i=0;i<columnsList.size();i++){
                    List<AscoOrderForm> batch=columnsList.get(i);
                    exe.execute(new Runnable(){
                        @Override
                        public void run() {
                            log.info("------two star------");
                            for(int i=0;i<batch.size();i++){
                                AscoOrderForm ascoOrder=batch.get(i);
                                //if(ascoOrder.getAddressAttn().contains("配送")){
                                //查询地址默认自带江西省
                                String addressAttn="江西省"+ascoOrder.getAddressAttn();
                                //一条一条查
                                secondCallInterfaceEncapsulateData(ascoOrder,addressAttn,i);
                            }
                        }
                    });
                }
                exe.shutdown();
                while (true) {
                    if (exe.isTerminated()) {
                        //log.debug("线程执行完毕开始插入数据！");
                        log.info("第二次线程执行完毕！");
                        this.saveOrUpdateBatch(columns);
                        break;
                    }
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

//        int num=0;
//        StringBuilder address=new StringBuilder();
//
//        List<AscoOrderForm> tempAscoOrderList=null;

//        for(int i=0;i<columns.size();i++){
//            AscoOrderForm ascoOrder=columns.get(i);
//            //if(ascoOrder.getAddressAttn().contains("配送")){
//            //查询地址默认自带江西省
//            String addressAttn="江西省"+ascoOrder.getAddressAttn();
//            //一条一条查
//            secondCallInterfaceEncapsulateData(ascoOrder,addressAttn,i);

            //每10条数据(高德接口只提供最多10条记录)调用一次高德查询坐标接口和 根据坐标获取第四级(乡镇，街道级)地址接口
            /*if(num==10){
                //num=0;//重新循环
                callInterfaceEncapsulateData(tempAscoOrderList,address.toString(),i);

                //开始下一次循环
                address=new StringBuilder();//清空查询路径
                address.append(addressAttn+"|");
                tempAscoOrderList=new ArrayList<AscoOrderForm>(); //清空临时数据
                tempAscoOrderList.add(ascoOrder);
                num=1;
            }else{
                if(i==columns.size()-1){//最后一条
                    address.append(addressAttn);
                    if(tempAscoOrderList==null){
                        tempAscoOrderList=new ArrayList<AscoOrderForm>();
                    }
                    tempAscoOrderList.add(ascoOrder);
                    callInterfaceEncapsulateData(tempAscoOrderList,address.toString(),i);
                }else{
                    if(num==9){
                        address.append(addressAttn);
                    }else{
                        address.append(addressAttn+"|");
                    }
                    if(tempAscoOrderList==null){
                        tempAscoOrderList=new ArrayList<AscoOrderForm>();
                    }
                    tempAscoOrderList.add(ascoOrder);
                    num+=1;
                    continue;
                }
            }*/
//        }
    }



    /*调用高德接口返回数据并且封装数据*/
    private void callInterfaceEncapsulateData(List<AscoOrderForm> tempAscoOrderList,String address,int index){//List<AscoOrderForm> ascoOrderList,
//        log.error("error接口调用，第"+index+"行；");
//        log.debug("debug接口调用，第"+index+"行；");
//        log.info("info接口调用，第"+index+"行；");
        int errIndex=index+1;
        List<AddressVo> avList=null;
        try {
            avList= getLocation(address.toString());
        } catch (CustomException e) {
            //throw new ApiException("9999",null,"系统异常,在"+errIndex+"行附近!");
            log.error("9999",null,"系统异常,在"+errIndex+"行附近!");
            return;
        }

        if(avList==null||avList.size()==0){
            //地址有误,第i条附近
            //throw new ApiException("500", null, "获取地址坐标数据异常,在"+errIndex+"行附近!");
            log.error("9999",null,"系统异常,在"+errIndex+"行附近!");
            return;
        }


        // 将坐标抽取出来做成List
//        List<String> coordsList = avList.stream().map(AddressVo::getAddress).collect(Collectors.toList());
        StringBuilder location = new StringBuilder();
        //记录返回坐标为空的角标(tempAscoOrderList临时列表序列号)
        Map<String, String> emptyLocalMap=new HashMap<String, String>();

        for(int i=0;i<avList.size();i++){
            AddressVo addressVo=avList.get(i);
//            String city=addressVo.getCity();
            String district=addressVo.getDistrict();//区
            String coords=addressVo.getAddress();//坐标
            if(!"[]".equals(coords)){
                //查询时加江西省，如果返回的地区是省，说明查的不对，筛除掉
                if("省".equals(district)){
                    emptyLocalMap.put(i+"",i+"");
                }else{
                    //拼接查询坐标
                    location.append(coords).append("|");
                }
            }else{
                emptyLocalMap.put(i+"",i+"");
            }
        }

        if(location.length() > 0){
            location.delete(location.length()-1,location.length());
        }
        Map<String, Object> map = new HashMap<>();
        try {
            map.put("location", URLEncoder.encode(location.toString(),"utf-8"));
            map.put("key", gaode_key);//iTrackServiceService.getDefaultKey().getGaodeKey()
            //map.put("key", iTrackServiceService.getDefaultKey().getGaodeKey());
            map.put("batch","true");
        } catch (UnsupportedEncodingException e) {
            //throw new ApiException("9999",null,"系统异常,在"+errIndex+"行附近!");
            log.error("9999",null,"系统异常,在"+errIndex+"行附近!");
            return;
        }
        // 根据坐标查询第四级
        Map<String, Object> resultMap =null;
        try{
            resultMap =apiHelperService.executeApi("getAddressByLocation",map);
        }catch (Exception e){
            log.debug("获取地址坐标请求连接异常,在"+errIndex+"行附近!");
            //throw new ApiException("404", null, "获取地址坐标请求连接异常,在"+errIndex+"行附近!");
            return;
        }

        if (resultMap == null) {
//            throw new ApiException("404", null, "获取地址坐标请求连接异常,在"+errIndex+"行附近!");
            return;
        } else {
            //成功
            if (Integer.parseInt(resultMap.get("status").toString()) == 1) {
                //获取乡镇代码
                List<Map<String, Object>> regeocodes = (List<Map<String, Object>>) resultMap.get("regeocodes");

                //删除没有找到坐标的记录,返回有坐标的集合
                List<AscoOrderForm> returnAscoOrderList=null;
                if(emptyLocalMap.size()!=0){
                    returnAscoOrderList=new ArrayList<AscoOrderForm>();
                    for(int j=0;j<tempAscoOrderList.size();j++){
                        if(!emptyLocalMap.containsKey(j+"")){
                            returnAscoOrderList.add(tempAscoOrderList.get(j));
                        }
                    }
                }else{
                    returnAscoOrderList=tempAscoOrderList;
                }
                if(regeocodes.size()!=returnAscoOrderList.size()){
                    //throw new ApiException("500", null, "获取第四级地址坐标数据异常,在"+errIndex+"行附近!");
                    //不报错，直接下一轮
                    return;
                }

                for (int j = 0; j < regeocodes.size(); j++){
                    Map<String, Object> addressComponent = regeocodes.get(j);
                    Map<String, Object> townMap = (Map<String, Object>) addressComponent.get("addressComponent");
                    //批量返回的第四级匹配 （筛除查询不到坐标的记录）当前批次查询的集合数据
                    AscoOrderForm theAscoOrder=returnAscoOrderList.get(j);
                    String provinceAttn= (String) townMap.get("province");
                    String storeName=theAscoOrder.getItemName();
                    if("江西省".equals(provinceAttn)){
                        setExcelDate(townMap,theAscoOrder,provinceAttn,null);
                    }else{//不是四平电商，又是外省的数据，不处理
                        if("四平电商".equals(storeName)){
                            setExcelDate(townMap,theAscoOrder,provinceAttn,"四平电商");
                        }
                    }
                }
            }
        }
    }



    /*第二次调用高德接口返回数据并且封装数据*/
    private void secondCallInterfaceEncapsulateData(AscoOrderForm ascoOrder,String address,int index){
        //List<AddressVo> avList= getLocation(address.toString());
        List<AddressVo> avList=null;
        try {
            avList= getLocation(address.toString());
        } catch (CustomException e) {
            //throw new ApiException("9999",null,"系统异常,在"+index+"行附近!");
            log.error("9999",null,"系统异常,在"+index+"行附近!");
            return;
        }
        if(avList==null||avList.size()==0){
            log.error("9999",null,"系统异常,在"+index+"行附近!");
            return;
        }
        StringBuilder location = new StringBuilder();

        // 将坐标抽取出来做成List
//        List<String> coordsList = avList.stream().map(AddressVo::getAddress).collect(Collectors.toList());
        //记录返回坐标为空的角标(tempAscoOrderList临时列表序列号)
        Map<String, String> emptyLocalMap=new HashMap<String, String>();

//        for(int i=0;i<avList.size();i++){
            AddressVo addressVo=avList.get(0);
//            String city=addressVo.getCity();
            String district=addressVo.getDistrict();//区
            String coords=addressVo.getAddress();//坐标
            if(!"[]".equals(coords)){
                //查询时加江西省，如果返回的地区是省，说明查的不对，筛除掉
                if("省".equals(district)){
                    return;
                }else{
                    //拼接查询坐标
                    location.append(coords);
                }
            }else{
                return;
            }
//        }
        Map<String, Object> map = new HashMap<>();
        try {
            map.put("location", URLEncoder.encode(location.toString(),"utf-8"));
            map.put("key", gaode_key);//iTrackServiceService.getDefaultKey().getGaodeKey
            //map.put("key", iTrackServiceService.getDefaultKey().getGaodeKey());
            map.put("batch","true");
        } catch (UnsupportedEncodingException e) {
            //throw new ApiException("9999",null,"系统异常,错误地址："++address);
            log.debug("接口调用出错；原因："+e.getMessage());
            return;
        }
        // 根据坐标查询第四级

        Map<String, Object> resultMap =null;
        try{
            resultMap =apiHelperService.executeApi("getAddressByLocation", map);
        }catch (Exception e){
//            log.error("接口调用出错，第"+index+"行；原因："+e.getMessage());
            log.debug("接口调用出错；原因："+e.getMessage());
            return;
        }
        if (resultMap == null) {
            //throw new ApiException("404", null, "获取地址坐标请求连接异常,错误地址："+address);
            return;
        } else {
            //成功
            if (Integer.parseInt(resultMap.get("status").toString()) == 1) {
                //获取乡镇代码
                List<Map<String, Object>> regeocodes = (List<Map<String, Object>>) resultMap.get("regeocodes");

                for (int j = 0; j < regeocodes.size(); j++){
                    Map<String, Object> addressComponent = regeocodes.get(j);
                    Map<String, Object> townMap = (Map<String, Object>) addressComponent.get("addressComponent");
                    //批量返回的第四级匹配 （筛除查询不到坐标的记录）当前批次查询的集合数据
                    String provinceAttn= (String) townMap.get("province");
                    String storeName=ascoOrder.getItemName();
                    setExcelDate(townMap,ascoOrder,provinceAttn,null);
                    //if("江西省".equals(provinceAttn)&&!"四平电商".equals(storeName)){
//                        setExcelDate(townMap,ascoOrder,provinceAttn);
                    //}
                }
            }
        }
    }


    private void setExcelDate(Map<String, Object> townMap,AscoOrderForm theAscoOrder,String provinceAttn,String dataType){
        String cityAttn=null;
        if(townMap.get("city") instanceof String){
            cityAttn= (String) townMap.get("city");
        }
        String districtAttn= null;
        if(townMap.get("district") instanceof String){
            districtAttn= (String) townMap.get("district");
        }

        String township=null;
        //towncode
        if(townMap.get("township") instanceof String){
            township=((String) townMap.get("township"));
        }
        String administrativeAttn=provinceAttn;

        if(cityAttn!=null){
            administrativeAttn+="/"+cityAttn;
            theAscoOrder.setCityAttn(cityAttn);
        }
        if(districtAttn!=null){
            administrativeAttn+="/"+districtAttn;
            theAscoOrder.setDistrictAttn(districtAttn);
        }
        if(township!=null&&!"四平电商".equals(dataType)){
            administrativeAttn+="/"+township;
        }
        //如果省有值，但是市区都没有值，说明查的不对不保存。
        if(cityAttn!=null||districtAttn!=null){
            theAscoOrder.setProvinceAttn(provinceAttn);
            theAscoOrder.setAdministrativeAttn(administrativeAttn);
        }
    }
    /**
     * 根据名称获取坐标
     * @param address
     * @return
     */
    private List<AddressVo> getLocation(String address) {
        Map<String, Object> map = new HashMap<>();
        List<AddressVo> avList = new ArrayList<>();
        try {
            map.put("address", URLEncoder.encode(address,"utf-8"));
        } catch (UnsupportedEncodingException e) {
            throw new CustomException(ErroEnums.SYSERRO.getCode(),new String[]{"请求地址为:" + address},ErroEnums.SYSERRO.getInfo() + "系统异常");
        }
        map.put("key", gaode_key);//iTrackServiceService.getDefaultKey().getGaodeKey(),gaode_key
        //map.put("key", iTrackServiceService.getDefaultKey().getGaodeKey());
        map.put("batch","true");
        Map<String, Object> resultMap = apiHelperService.executeApi("geocode", map);
        if (resultMap == null) {
            throw new CustomException(ErroEnums.APIERRO.getCode(), new String[]{"请求地址为:" + address}, ErroEnums.APIERRO.getInfo() + "获取地址坐标请求连接异常");
        } else {
            if(resultMap.size()<1){
                return null;
                //throw new ApiException("404", null, "没有获取到数据");
            }
            //成功
            if (Integer.parseInt(resultMap.get("status").toString()) == 1) {
                //获取地址坐标数据
                List<Map<String, Object>> geocodes = (List<Map<String, Object>>) resultMap.get("geocodes");
                if (geocodes == null || geocodes.size() == 0) {
                    throw new CustomException(ErroEnums.BUSERRO.getCode(), new String[]{"请求结果:" + JSON.toJSONString(resultMap)}, ErroEnums.BUSERRO.getInfo() + "无法解析地址信息");
                }
                for (int i = 0; i< geocodes.size();i++){
                    AddressVo av = new AddressVo();
                    Map<String, Object> geocode = geocodes.get(i);
                    String location = geocode.get("location").toString();
                    av.setAddress(location);
                    av.setDistrict(geocode.get("level").toString());
                    avList.add(av);
                }
                return avList;
            }
        }
        return null;
    }

    private List<AscoOrderForm> queryListByAscoOrderForm(AscoOrderForm ascoOrderForm) {

        // batch_index= and administrative_attn is null
        // and address_attn ( notlike 'NULL' and !='')
        //and address_attn not like '%配送%'    配送的不查
        // or province_attn !='江西省' and item_name !='四平电商'
        //查询当前批次 并且行政区划字段为空(第一遍没有更新到) 并且 详细地址不等于'NULLNULL'(excel导入的数据有问题),或者省份不是江西省并且门店不是四平电商的数据
        LambdaQueryWrapper<AscoOrderForm> lqw = Wrappers.lambdaQuery();
        lqw.eq(AscoOrderForm::getBatchIndex ,ascoOrderForm.getBatchIndex());
        lqw.isNull(AscoOrderForm::getAdministrativeAttn);
        //lqw.isNotNull(AscoOrderForm::getAddressAttn);
        lqw.ne(AscoOrderForm::getAddressAttn ,"");//不等于""字符串
        lqw.notLike(AscoOrderForm::getAddressAttn,"%NULL%");
        lqw.notLike(AscoOrderForm::getAddressAttn,"%配送%");
//        lqw.or().ne(AscoOrderForm::getProvinceAttn ,ascoOrderForm.getProvinceAttn());
        lqw.ne(AscoOrderForm::getItemName ,ascoOrderForm.getItemName());
        return this.list(lqw);
    }


    private boolean queryAddressAndInsertExcelData(List<AscoOrderForm> columns,String batchIndex){

        //导入数据的逻辑
        //根据收件人详细地址去获取高德坐标，再根据坐标去获取第四级(乡、镇、街道级)，反写回excel保存到表中
        //步骤：1,判断收件人地址是否含有'配送',有做特殊处理(根据门店地址去获取高德坐标)
        //2,每10条数据请求一次高德获取坐标地址接口,再根据坐标请求接口查询第四级
        int num=0;
        StringBuilder address=new StringBuilder();

        List<AscoOrderForm> tempAscoOrderList=null;
        //
        Map<String,AscoOrderForm> storeAddressMap=new HashMap<String,AscoOrderForm>();

        for(int i=0;i<columns.size();i++){
            AscoOrderForm ascoOrder=columns.get(i);
            ascoOrder.setRemark("C");//暂时把这个当状态字段来用
            ascoOrder.setBatchIndex(batchIndex);

            //if(ascoOrder.getAddressAttn().contains("配送")){
            String rgion=ascoOrder.getRegion();
            String excAddress=ascoOrder.getAddress();
            String addressAttn=rgion+excAddress;
            addressAttn=addressAttn.replaceAll(" ","");

            //不处理跳过
            if("NULL".equals(rgion)||"NULL".equals(excAddress)||"".equals(addressAttn)){
                ascoOrder.setAddressAttn(addressAttn);
                //为空的数据不处理
                continue;
            }
            //详细地址excel中是公式(rgion区域+address地址)，拿不到值，反向set回去
            ascoOrder.setAddressAttn(addressAttn);
            //处理特殊地址并且直接返回值不调接口
            if(processOtherAdressSetValue(ascoOrder)){
                continue;
            }
            //处理特特殊地址
            addressAttn=processOtherAdress(addressAttn);
            if(addressAttn.indexOf("配送")>0&&!"四平电商".equals(ascoOrder.getItemName())){
                //根据门店获取渠道
                String storeName=ascoOrder.getItemName();
                //这家店没有同步到，直接写死
                if("四平电器赣县润达店".equals(storeName)){
                    ascoOrder.setProvinceAttn("江西省");
                    ascoOrder.setCityAttn("赣州市");
                    ascoOrder.setDistrictAttn("赣县区");
                    ascoOrder.setAdministrativeAttn("江西省/赣州市/赣县区/梅林镇");
                    //直接取行政区划的值，不调接口查询
                    continue;
                }
                if(storeAddressMap.containsKey(storeName)){//已经查过这家门店的行政区划
                    ascoOrder.setProvinceAttn(storeAddressMap.get(storeName).getProvinceAttn());
                    ascoOrder.setCityAttn(storeAddressMap.get(storeName).getCityAttn());
                    ascoOrder.setDistrictAttn(storeAddressMap.get(storeName).getDistrictAttn());
                    ascoOrder.setAdministrativeAttn(storeAddressMap.get(storeName).getAdministrativeAttn());
                    //直接取行政区划的值，不调接口查询
                    continue;
                }else{
                    KdQdfile searchQdfile=new KdQdfile();
                    searchQdfile.setName(storeName);
                    List<KdQdfile> adminDivisionList = iKdQdfileService.queryList(searchQdfile);
                    if(adminDivisionList==null||adminDivisionList.size()==0){
                        //throw new DataException("500", null, "未找到匹配的门店,"+storeName+"!");
                        continue;
                    }else{
                        AdminDivision adminDivision=new AdminDivision();
                        String area=adminDivisionList.get(0).getArea();
                        adminDivision.setId(Long.parseLong(area));
                        //
                        List<AdminDivision> list=iAdminDivisionService.getList(adminDivision);
                        if(list==null||list.size()==0){
                            throw new CustomException(ErroEnums.DATAERRO.getCode(), new Object[]{}, "未找到匹配门店的行政区划，"+storeName+"行!");
                        }
                        String fullName=list.get(0).getFullName();
                        String[] addressArr=fullName.split("_");
                        if(addressArr.length>=3){
                            ascoOrder.setProvinceAttn(addressArr[0]);
                            ascoOrder.setCityAttn(addressArr[1]);
                            ascoOrder.setDistrictAttn(addressArr[2]);
                            addressAttn=fullName.replaceAll("_","/");
                            ascoOrder.setAdministrativeAttn(addressAttn);
                            storeAddressMap.put(storeName,ascoOrder);
                        }
                        //addressAttn=fullName.replaceAll("_","");
                        //直接取行政区划的值，不调接口查询
                        continue;
                    }
                }
            }

            //每10条数据(高德接口只提供最多10条记录)调用一次高德查询坐标接口和 根据坐标获取第四级(乡镇，街道级)地址接口
            if(num==10){
                //num=0;//重新循环
                callInterfaceEncapsulateData(tempAscoOrderList,address.toString(),i);

                //开始下一次循环
                address=new StringBuilder();//清空查询路径
                address.append(addressAttn+"|");
                tempAscoOrderList=new ArrayList<AscoOrderForm>(); //清空临时数据
                tempAscoOrderList.add(ascoOrder);
                num=1;
            }else{
                if(i==columns.size()-1){//最后一条
                    address.append(addressAttn);
                    if(tempAscoOrderList==null){
                        tempAscoOrderList=new ArrayList<AscoOrderForm>();
                    }
                    tempAscoOrderList.add(ascoOrder);
                    callInterfaceEncapsulateData(tempAscoOrderList,address.toString(),i);
                }else{
                    if(num==9){
                        address.append(addressAttn);
                    }else{
                        address.append(addressAttn+"|");
                    }
                    if(tempAscoOrderList==null){
                        tempAscoOrderList=new ArrayList<AscoOrderForm>();
                    }
                    tempAscoOrderList.add(ascoOrder);
                    num+=1;
                    continue;
                }
            }
        }
        boolean insertflag=true;//saveBatch(columns);
        //if (this.saveBatch(columns)) {
        //    successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + columns.size() + " 条，数据如下：");
        //} else {
        //    throw new DataException("500", null, "保存表的列数据异常");
        //}
        return insertflag;
    }
    //是否启动多线程
    private int isOrStartMultithreading(List<AscoOrderForm> columns,String batchIndex) {
        int num=0;
        log.info("开始调接口封装数据！");
        if(columns.size()<=2000){
            boolean flag=queryAddressAndInsertExcelData(columns,batchIndex);
            if(flag){
                this.saveBatch(columns);
                num=columns.size();
            }
        }else{
            ExecutorService exe = Executors.newFixedThreadPool(50);
            //List<List<AscoOrderForm>> columnsList=averageAssign(columns,2000);
            List<List<AscoOrderForm>> columnsList=fixedGrouping(columns,2000);
//            final boolean[] flagArr = new boolean[columnsList.size()];
//            int overSize=0;//记录最后一个集合的数量
            for(int i=0;i<columnsList.size();i++){
                List<AscoOrderForm> batch=columnsList.get(i);
                exe.execute(new Runnable(){
                    @Override
                    public void run() {
                        log.info("------star------");
                        queryAddressAndInsertExcelData(batch,batchIndex);
                    }
                });
            }
            exe.shutdown();
            while (true) {
                if (exe.isTerminated()) {
                    //log.debug("线程执行完毕开始插入数据！");
                    log.info("线程执行完毕开始插入数据！");
                    //System.out.println("结束了！");
                    //this.saveBatch(columns);
                    List<List<AscoOrderForm>> saveList=fixedGrouping(columns,500);
                    for(int i=0;i<saveList.size();i++) {
                        List<AscoOrderForm> bat = saveList.get(i);
                        this.saveBatch(bat);
                    }
                    //log.debug("第一次插入数据完毕！");
                    log.info("第一次插入数据完毕！");
                    break;
                }
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return num;
    }

    /**
     * 将一组数据平均分成n组
     *
     * @param source 要分组的数据源
     * @param n      平均分成n组
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> averageAssign(List<T> source, int n) {
        List<List<T>> result = new ArrayList<List<T>>();
        int remainder = source.size() % n;  //(先计算出余数)
        int number = source.size() / n;  //然后是商
        int offset = 0;//偏移量
        for (int i = 0; i < n; i++) {
            List<T> value = null;
            if (remainder > 0) {
                value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
                remainder--;
                offset++;
            } else {
                value = source.subList(i * number + offset, (i + 1) * number + offset);
            }
            result.add(value);
        }
        return result;
    }
    /**
     * 将一组数据固定分组，每组n个元素
     * @param source 要分组的数据源
     * @param n      每组n个元素
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> fixedGrouping(List<T> source, int n) {

        if (null == source || source.size() == 0 || n <= 0)
            return null;
        List<List<T>> result = new ArrayList<List<T>>();

        int sourceSize = source.size();
        int size = (source.size() / n) + 1;
        for (int i = 0; i < size; i++) {
            List<T> subset = new ArrayList<T>();
            for (int j = i * n; j < (i + 1) * n; j++) {
                if (j < sourceSize) {
                    subset.add(source.get(j));
                }
            }
            result.add(subset);
        }
        return result;
    }
}
